package com.google.jessewilson.codesearch.api;

import com.google.jessewilson.codesearch.io.UriSplicer;

import java.net.URI;
import java.net.URISyntaxException;

/**
 * A source for source code.
 *
 * @author jessewilson
 */
public abstract class ContentRoot implements Comparable<ContentRoot> {

  /**
   * Returns the name of the content, such as "glazedlists-1.5.0.zip".
   */
  public abstract String getContentName();

  /**
   * Returns the path to the content, such as
   * "http://publicobject.com/glazedlists/releases/"
   */
  public abstract String getContentPath();

  public int compareTo(ContentRoot other) {
    int result = 0;

    // compare by content path first
    result = compare(getContentPath(), other.getContentPath());
    if (result != 0) {
      return result;
    }

    // then by content name
    result = compare(getContentName(), other.getContentName());
    if (result != 0) {
      return result;
    }

    return 0;
  }
  private int compare(String a, String b) {
    if(a == b) return 0;
    return a == null ? -1 : a.compareTo(b);
  }

  public static ContentRoot fromString(String contentRoot) {
    // try to convert the content root to a URI
    try {
      return new UriContentRoot(new URI(contentRoot));
    } catch(URISyntaxException e) {
      // wasn't an URI, try another method
    }

    return new GenericContentRoot(contentRoot);
  }

  public String toString() {
    String contentName = getContentName();
    String contentPath = getContentPath();
    if(contentName != null) {
      if(contentPath != null) {
        return contentName + " at " + contentPath;
      } else {
        return contentName;
      }
    } else if(contentPath != null) {
      return contentPath;
    } else {
      return "";
    }
  }

  /**
   * Model a content root such an archive file on an HTTP or FTP server.
   */
  private static class UriContentRoot extends ContentRoot {
    private static final UriSplicer splicer = new UriSplicer();
    private final URI uri;
    private final String contentName;
    private final String contentPath;
    public UriContentRoot(URI uri) {
      this.uri = uri;
      this.contentName = splicer.getFileName(uri);
      this.contentPath = splicer.getParentUri(uri).toString();
    }

    public String getContentName() {
      return contentName;
    }

    public String getContentPath() {
      return contentPath;
    }

    public boolean equals(Object o) {
      if(this == o) return true;
      if(o == null || getClass() != o.getClass()) return false;
      UriContentRoot that = (UriContentRoot) o;
      if(!uri.equals(that.uri)) return false;
      return true;
    }
    public int hashCode() {
      return uri.hashCode();
    }

  }

  /**
   * Model a content root such as a CVS or subversion server.
   */
  private static class GenericContentRoot extends ContentRoot {
    private final String contentRoot;
    public GenericContentRoot(String contentRoot) {
      this.contentRoot = contentRoot;
    }

    public String getContentName() {
      return null;
    }

    public String getContentPath() {
      return contentRoot;
    }
  }

}
